import java.util.*;

public class Statement {

    public static final char COMMENT_LEADER = '#';

    private String source;

    private Token entire;
    private Token stripped;
    private Token label;
    private Token mnemonic;
    private Token operand;
    private Token junk;

    private int address;
    private int codeLength;
    private int machineCode;

    private int findChar(char ch, int i) {
	int entireEnd = entire.getEnd();
	while (i < entireEnd && source.charAt(i) != ch) {
	    i++;
	}
	return i;
    }

    private int findWhitespace(int i) {
	int strippedEnd = stripped.getEnd();
	while (i < strippedEnd && !Character.isWhitespace(source.charAt(i))) {
	    i++;
	}
	return i;
    }

    private int findNonwhitespace(int i) {
	int strippedEnd = stripped.getEnd();
	while (i < strippedEnd && Character.isWhitespace(source.charAt(i))) {
	    i++;
	}
	return i;
    }

    private Token getToken(int s) {
	int tokenStart = findNonwhitespace(s);
	int tokenEnd = findWhitespace(tokenStart);
	return new Token(source, tokenStart, tokenEnd);
    }

    public Statement(String src, int s) {
	source = src;
	int entireEnd = source.indexOf('\n', s);
	if (entireEnd == -1) {
	    entireEnd = source.length();
	}
	entire = new Token(source, s, entireEnd);
	getStripped();
	codeLength = 0;
    }

    public Token getEntire() {
	return entire;
    }

    public Token getStripped() {
	if (stripped == null) {
	    int strippedStart = getEntire().getStart();
	    int strippedEnd = findChar(COMMENT_LEADER, strippedStart);
	    while (strippedEnd > strippedStart) {
		if (!Character.isWhitespace(source.charAt(strippedEnd - 1))) {
		    break;
		}
		strippedEnd--;
	    }
	    stripped = new Token(source, strippedStart, strippedEnd);
	}
	return stripped;
    }

    public Token getLabel() {
	if (label == null) {
	    int labelStart = stripped.getStart();
	    int labelEnd = findWhitespace(labelStart);
	    label = new Token(source, labelStart, labelEnd);
	}
	return label;
    }

    public Token getMnemonic() {
	if (mnemonic == null) {
	    mnemonic = getToken(getLabel().getEnd());
	}
	return mnemonic;
    }

    public Token getOperand() {
	if (operand == null) {
	    operand = getToken(getMnemonic().getEnd());
	}
	return operand;
    }

    public Token getJunk() {
	if (junk == null) {
	    int junkStart = findNonwhitespace(getOperand().getEnd());
	    junk = new Token(source, junkStart, getStripped().getEnd());
	}
	return junk;
    }

    public void assignCode(int addr, int cl, int mc) {
	address = addr;
	codeLength = cl;
	machineCode = mc;
    }

    public int getAddress() {
	return address;
    }

    public int getCodeLength() {
	return codeLength;
    }

    public int getMachineCode() {
	return machineCode;
    }

    public void setAddress(int addr) {
	address = addr;
    }

    public void setMachineCode(int mc) {
	machineCode = mc;
	codeLength = 1;
    }

}

